﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.ETL
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class TablePartitionInstruction:InstructionBase
    {
        #region props
        private string _ConnStr;
        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._ConnStr;
            }
            set
            {
                this._ConnStr = value;
            }
        }

        private string _SchemaName;
        /// <summary></summary>
        public string SchemaName
        {
            get
            {
                return this._SchemaName;
            }
            set
            {
                this._SchemaName = value;
            }
        }

        private string _TblName;
        /// <summary></summary>
        public string TblName
        {
            get
            {
                return this._TblName;
            }
            set
            {
                this._TblName = value;
            }
        }

        private List<string> _PartitionFields;
        /// <summary></summary>
        public List<string> PartitionFields
        {
            get
            {
                return this._PartitionFields;
            }
            set
            {
                this._PartitionFields = value;
            }
        }

        private bool _GroupByFieldValue;
        /// <summary></summary>
        public bool GroupByFieldValue
        {
            get
            {
                return this._GroupByFieldValue;
            }
            set
            {
                this._GroupByFieldValue = value;
            }
        }

        private int _RecordPerTable;
        /// <summary></summary>
        public int RecordPerTable
        {
            get
            {
                return this._RecordPerTable;
            }
            set
            {
                this._RecordPerTable = value;
            }
        }

        private string _OutputTablePrefix;
        /// <summary></summary>
        public string OutputTablePrefix
        {
            get
            {
                return this._OutputTablePrefix;
            }
            set
            {
                this._OutputTablePrefix = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public TablePartitionInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._ConnStr = string.Empty;
            this._SchemaName = string.Empty;
            this._TblName = string.Empty;
            this._PartitionFields = new List<string>();
            this._GroupByFieldValue = false;
            this._OutputTablePrefix = string.Empty;
            this._RecordPerTable = 1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="componentID"></param>
        /// <param name="jobTicketID"></param>
        /// <param name="connStr"></param>
        /// <param name="schemaName"></param>
        /// <param name="tblName"></param>
        /// <param name="partitionFields"></param>
        /// <param name="groupByValue"></param>
        /// <param name="prefix"></param>
        /// <param name="count"></param>
        public TablePartitionInstruction(
            Guid componentID, Guid jobTicketID,
            string connStr, string schemaName, string tblName,
            List<string> partitionFields, bool groupByValue,
            string prefix, int count) 
            : base(componentID, jobTicketID)
        {
            this._ConnStr = connStr;
            this._SchemaName = schemaName;
            this._TblName = tblName;
            this._PartitionFields = partitionFields;
            this._GroupByFieldValue = groupByValue;
            this._OutputTablePrefix = prefix;
            this._RecordPerTable = count;
        }
        #endregion

        #region Overrides of InstructionBase

        /// <summary>
        /// serialize settings to xml
        /// the function below is mainly for storing into database as serialized form instead of string
        /// </summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode,"ConnStr",this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SchemaName", this.SchemaName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableName", this.TblName);
            XmlNode partitionNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "PartitionFields");
            if(this.PartitionFields !=null && this.PartitionFields.Count>0)
            {
                foreach(string field in this.PartitionFields)
                {
                    XmlNode partitionNode = XmlDataUtil.AddElement(ref xDoc, partitionNodes, "PartitionField");
                    XmlDataUtil.UpdateAttribute(ref xDoc, partitionNode,"FieldName",field);
                }
            }
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "GroupByValue", this.GroupByFieldValue.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "OutputPrefix", this.OutputTablePrefix);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "RecordPerTable", this.RecordPerTable.ToString());

            return xNode;
        }

        /// <summary>
        /// instantiated from xml
        /// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
        /// instantiate from first child of root node
        /// </summary>
        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                TablePartitionInstruction instruction = new TablePartitionInstruction();
                instruction.OwnerComponentID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "ComponentID", Guid.NewGuid().ToString()));
                instruction.OwnerWorkerInstanceID = new Guid(XmlDataUtil.GetAttributeValue(xNode, "WorkerID", Guid.NewGuid().ToString()));
                instruction.SubmitTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "SubmitTime", TimeUtil.DbMinTime.ToString()));
                instruction.StartTime = DateTime.Parse(XmlDataUtil.GetAttributeValue(xNode, "StartTime", TimeUtil.DbMinTime.ToString()));

                instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                instruction.SchemaName = XmlDataUtil.GetAttributeValue(xNode, "SchemaName", "");
                instruction.TblName = XmlDataUtil.GetAttributeValue(xNode, "TableName", "");
                instruction.PartitionFields = new List<string>();
                XmlNodeList partitionNodes = xNode.SelectNodes("PartitionFields/PartitionField");
                if(partitionNodes !=null && partitionNodes.Count>0)
                {
                    foreach(XmlNode partitionNode in partitionNodes)
                    {
                        instruction.PartitionFields.Add(XmlDataUtil.GetAttributeValue(partitionNode, "FieldName", ""));
                    }
                }
                instruction.GroupByFieldValue =
                    bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "GroupByValue", false.ToString()));
                instruction.OutputTablePrefix = XmlDataUtil.GetAttributeValue(xNode, "OutputPrefix", this.TblName);
                instruction.RecordPerTable = int.Parse(XmlDataUtil.GetAttributeValue(xNode, "RecordPerTable", "1"));
                                                                                                         
                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate component: invalid type specified in xml node");
            }
        }

        #endregion
    }
}
